from django.shortcuts import render
from rest_framework import viewsets, permissions
from .models import KData
from .serializers import KDataSerializer
from rest_framework.response import Response
from utils.binanceUtils import config
from binance.client import Client
from tradingPairs.models import TradingPairs
import datetime
from django.utils import timezone
# 获取配置参数
api_key = config.BinanceConfig.API_KEY
api_secret = config.BinanceConfig.API_SECRET
proxies = config.BinanceConfig.PROXIES
# 初始化客户端
client = Client(api_key, api_secret, {'proxies': proxies})
# K线周期
interval_one_hour = Client.KLINE_INTERVAL_1HOUR
interval_four_hour = Client.KLINE_INTERVAL_4HOUR
interval_12_hour = Client.KLINE_INTERVAL_12HOUR
interval_one_day = Client.KLINE_INTERVAL_1DAY
interval_one_week = Client.KLINE_INTERVAL_1WEEK


# Create your views here.
class KDataViewSet(viewsets.ModelViewSet):
    """
    K线数据视图集，提供从交易所API获取数据和本地数据聚合功能
    """
    permission_classes = [
        permissions.AllowAny
    ]
    queryset = KData.objects.all()
    serializer_class = KDataSerializer

    def get_data(self, request, *args, **kwargs):
        """
        从Binance API获取原始K线数据
        参数:
            pair_name: 交易对名称 (如BTCUSDT)
            cycle: K线周期 (1小时/4小时/12小时/24小时/1周)
        返回:
            处理后的分页K线数据，包含时区转换和时间戳格式化
        """
        # 解析请求参数
        trading_pair = request.query_params.get('pair_name')
        cycle = request.query_params.get('cycle')
        
        # 设置K线周期映射
        interval = interval_one_hour
        if cycle == "4小时":
            interval = interval_four_hour
        elif cycle == "12小时":
            interval = interval_12_hour
        elif cycle == "24小时":
            interval = interval_one_day
        elif cycle == "1周":
            interval = interval_one_week

        # 调用Binance API获取K线数据
        end_time = datetime.datetime.now()
        Kline = client.get_historical_klines(
            symbol=trading_pair,
            interval=interval,
            end_str=end_time.strftime("%Y-%m-%d %H:%M:%S"),
            limit=1000
        )

        # 数据转换：将原始K线数据转换为本地存储格式
        trading = TradingPairs.objects.get(id=1)
        data = []
        for kline in Kline:
            data.append({
                "trading_pair_id": trading,
                # 转换时间戳为东八区时间
                "time": datetime.datetime.fromtimestamp(kline[0]/1000, tz=datetime.timezone(datetime.timedelta(hours=8))),
                "open": float(kline[1]),
                "high": float(kline[2]),
                "low": float(kline[3]),
                "close": float(kline[4]),
                "volume": float(kline[5])
            })
        
        # 数据反向排序（交易所返回的是倒序）
        data = data[::-1]
        
        # 更新交易对数据结束时间（整点对齐）
        TradingPairs.objects.filter(trading_pair=trading_pair).update(
            data_end=end_time.replace(minute=0, second=0, microsecond=0).strftime("%Y-%m-%d %H:%M:%S")
        )

        # 分页返回结果
        page = self.paginate_queryset(data)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        else:
            return Response({
                "code": 400,
                "data": None,
                "message": "分页失败"
            })

    def get_data_v2(self, request, *args, **kwargs):
        """
        本地数据聚合接口（支持多周期）
        参数:
            pair_name: 交易对名称
            cycle: 聚合周期
            close: 收盘时间点（如"0点"）
        返回:
            聚合后的分页K线数据
        """
        # 获取请求参数
        trading_pair = request.query_params.get('pair_name')
        cycle = request.query_params.get('cycle')
        close = request.query_params.get('close')
        
        # 获取交易对ID
        trading_pair_id = TradingPairs.objects.get(trading_pair=trading_pair).id
        
        # 获取基础数据
        data = KData.objects.filter(trading_pair_id=trading_pair_id)
        
        # 执行数据聚合（非1小时周期）
        if cycle != "1小时":
            data = self.aggregate(data, cycle, close, trading_pair_id)
        
        # 分页返回结果
        page = self.paginate_queryset(data)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        else:
            return Response({
                "code": 400,
                "data": None,
                "message": "分页失败"
            })

    def aggregate(self, data, cycle, close, trading_pair_id):
        """
        数据聚合核心算法
        参数:
            data: QuerySet 原始数据
            cycle: 聚合周期（小时数）
            close: 收盘时间点（小时）
            trading_pair_id: 交易对ID
        返回:
            聚合后的数据列表，包含OHLC和成交量
        """
        # 参数转换
        close_hour = int(close.split('点')[0])
        cycle_hours = int(cycle.split('小时')[0])
        BTC = TradingPairs.objects.get(id=trading_pair_id)
        
        # 转换为列表提升查询性能
        data_list = list(data)  
        
        # 寻找第一个符合收盘时间的起始点
        start_index = 0
        for item in data_list:
            if item.time.hour == close_hour:
                start_index = data_list.index(item)
                break
                
        # 执行聚合计算
        aggregate = []
        while start_index + cycle_hours <= len(data_list):
            temp = data[start_index:start_index + cycle_hours]
            
            # 计算OHLC和成交量
            max_high = -1.0
            min_low = 9999999999999999999999999999999999.99999
            volume = 0.0
            for item in temp:
                max_high = max(max_high, item.high)
                min_low = min(min_low, item.low)
                volume += item.volume
                
            # 构建聚合后的K线数据
            time_temp = temp[0].time
            aggregate.append({
                "trading_pair_id": BTC,
                "time": time_temp,
                "open": temp[0].open,
                "high": max_high,
                "low": min_low,
                "close": temp[-1].close,
                "volume": volume
            })
            start_index += cycle_hours
            
        return aggregate
